﻿using MCP.BL;
using MCP.Data.CF_Entities;
using MCP.Model.Repositories.Interfaces;
using System;
using System.Collections.Specialized;
using System.Configuration;
using System.Linq;
using System.Web.Configuration;
using System.Web.Security;

namespace MCP.Model.Auth
{
	public class MCPMembershipProvider : MembershipProvider
	{
		public override string ApplicationName
		{
			// NB: ApplicationName

			/*
		
			Membership providers store user information uniquely for each application.
			This enables multiple ASP.NET applications to use the same data source without
			running into a conflict if duplicate user names are created. Alternatively,
			multiple ASP.NET applications can use the same user data source by specifying
			the same ApplicationName.

			Because membership providers store user information uniquely for each
			application, you will need to ensure that your data schema includes
			the application name and that queries and updates also include
			the application name. For example, the following command is
			used to retrieve a user name from a database, based on the e-mail address,
			and ensures that the ApplicationName is included in the query.
		
			*/ 
			get
			{
				return "MoneyCounterProject";
			}
			set
			{
				throw new NotImplementedException();
			}
		}

		public override bool ChangePassword(string username, string oldPassword, string newPassword)
		{
			throw new NotImplementedException();
		}

		public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
		{
			throw new NotImplementedException();
		}

		public override MembershipUser CreateUser(
			string username,
			string password,
			string email,
			string passwordQuestion,
			string passwordAnswer,
			bool isApproved,
			object providerUserKey,
			out MembershipCreateStatus status)
		{
			throw new NotImplementedException();
		}

		public override void Initialize(string name = "MCPMembershipProvider", NameValueCollection config = null)
		{
			if (config == null)
			{
				string configPath = "~/web.config";
				Configuration NexConfig = WebConfigurationManager.OpenWebConfiguration(configPath);
				MembershipSection section = (MembershipSection)NexConfig.GetSection("system.web/membership");
				ProviderSettingsCollection settings = section.Providers;
				NameValueCollection membershipParams = settings[section.DefaultProvider].Parameters;
				config = membershipParams;
			}

			if (string.IsNullOrEmpty(name))
			{
				name = "MCPMembershipProvider";
			}

			if (string.IsNullOrEmpty(config["description"]))
			{
				config.Remove("description");
				config.Add("description", "Custom Membership Provider");
			}

			//Initialize the abstract base class.
			base.Initialize(name, config);

			//applicationName = GetConfigValue(config["applicationName"], System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
			//maxInvalidPasswordAttempts = Convert.ToInt32(GetConfigValue(config["maxInvalidPasswordAttempts"], "5"));
			//passwordAttemptWindow = Convert.ToInt32(GetConfigValue(config["passwordAttemptWindow"], "10"));
			//minRequiredNonAlphanumericCharacters = Convert.ToInt32(GetConfigValue(config["minRequiredAlphaNumericCharacters"], "1"));
			//minRequiredPasswordLength = Convert.ToInt32(GetConfigValue(config["minRequiredPasswordLength"], "7"));
			//passwordStrengthRegularExpression = Convert.ToString(GetConfigValue(config["passwordStrengthRegularExpression"], String.Empty));
			//enablePasswordReset = Convert.ToBoolean(GetConfigValue(config["enablePasswordReset"], "true"));
			//enablePasswordRetrieval = Convert.ToBoolean(GetConfigValue(config["enablePasswordRetrieval"], "true"));
			//requiresQuestionAndAnswer = Convert.ToBoolean(GetConfigValue(config["requiresQuestionAndAnswer"], "false"));
			//requiresUniqueEmail = Convert.ToBoolean(GetConfigValue(config["requiresUniqueEmail"], "true"));

			//string temp_format = config["passwordFormat"];
			//if (temp_format == null)
			//{
			//	temp_format = "Hashed";
			//}

			//switch (temp_format)
			//{
			//	case "Hashed":
			//		passwordFormat = MembershipPasswordFormat.Hashed;
			//		break;
			//	case "Encrypted":
			//		passwordFormat = MembershipPasswordFormat.Encrypted;
			//		break;
			//	case "Clear":
			//		passwordFormat = MembershipPasswordFormat.Clear;
			//		break;
			//	default:
			//		throw new ProviderException("Password format not supported.");
			//}

			//ConnectionStringSettings ConnectionStringSettings = ConfigurationManager.ConnectionStrings[config["connectionStringName"]];

			//if ((ConnectionStringSettings == null) || (ConnectionStringSettings.ConnectionString.Trim() == String.Empty))
			//{
			//	throw new ProviderException("Connection string cannot be blank.");
			//}

			//connectionString = ConnectionStringSettings.ConnectionString;

			////Get encryption and decryption key information from the configuration.
			//System.Configuration.Configuration cfg = WebConfigurationManager.OpenWebConfiguration(System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
			//machineKey = cfg.GetSection("system.web/machineKey") as MachineKeySection;

			//if (machineKey.ValidationKey.Contains("AutoGenerate"))
			//{
			//	if (PasswordFormat != MembershipPasswordFormat.Clear)
			//	{
			//		throw new ProviderException("Hashed or Encrypted passwords are not supported with auto-generated keys.");
			//	}
			//}
		}

		public MCPMembershipUser CreateNewUser(
			string username,
			string password,
			string email,
			string passwordQuestion,
			string passwordAnswer,
			bool isApproved,
			object providerUserKey,
			out System.Web.Security.MembershipCreateStatus status)
		{
			ValidatePasswordEventArgs args = new ValidatePasswordEventArgs(username, password, true);

			this.OnValidatingPassword(args);

			if (args.Cancel)
			{
				status = MembershipCreateStatus.InvalidPassword;
				return null;
			}

			////if ((this.RequiresUniqueEmail && (this.GetUserNameByEmail(email) != String.Empty)))
			////{
			////	status = MembershipCreateStatus.DuplicateEmail;
			////	return null;
			////}

			MCPMembershipUser customMembershipUser = this.GetUser(username);

			// User must not be in db.
			if (customMembershipUser == null)
			{
				try
				{
					using (MCPDB db = new MCPDB())
					{
						User user = new User()
						{
							Username = username,
							Password = password
						};
						////db.Users.InsertOnSubmit(user);
						////db.SubmitChanges();

						db.Users.Add(user);						

						status = MembershipCreateStatus.Success;

						return this.GetUser(username);
					}

				}
				catch
				{
					status = MembershipCreateStatus.ProviderError;
				}
			}
			else
			{
				status = MembershipCreateStatus.DuplicateUserName;
			}

			return null;
		}

		public override bool DeleteUser(string username, bool deleteAllRelatedData)
		{
			throw new NotImplementedException();
		}

		public override bool EnablePasswordReset
		{
			get { throw new NotImplementedException(); }
		}

		public override bool EnablePasswordRetrieval
		{
			get { throw new NotImplementedException(); }
		}

		public override System.Web.Security.MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
		{
			throw new NotImplementedException();
		}

		public override System.Web.Security.MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
		{
			throw new NotImplementedException();
		}

		public override System.Web.Security.MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
		{
			throw new NotImplementedException();
		}

		public override int GetNumberOfUsersOnline()
		{
			throw new NotImplementedException();
		}

		public override string GetPassword(string username, string answer)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Gets custom MCP MembershipUser by username.
		/// </summary>
		/// <param name="username">User name.</param>
		/// <returns>MCPMembershipUser</returns>
		public MCPMembershipUser GetUser(string username)
		{
			MCPMembershipUser CustomMembershipUser = new MCPMembershipUser(username);
			
			return CustomMembershipUser;
		}

		public override System.Web.Security.MembershipUser GetUser(string username, bool userIsOnline)
		{
			throw new NotImplementedException();
		}

		public override System.Web.Security.MembershipUser GetUser(object providerUserKey, bool userIsOnline)
		{
			throw new NotImplementedException();
		}

		public override string GetUserNameByEmail(string email)
		{
			throw new NotImplementedException();
		}

		public override int MaxInvalidPasswordAttempts
		{
			get { throw new NotImplementedException(); }
		}

		public override int MinRequiredNonAlphanumericCharacters
		{
			get { throw new NotImplementedException(); }
		}

		public override int MinRequiredPasswordLength
		{
			get { throw new NotImplementedException(); }
		}

		public override int PasswordAttemptWindow
		{
			get { throw new NotImplementedException(); }
		}

		public override System.Web.Security.MembershipPasswordFormat PasswordFormat
		{
			get { throw new NotImplementedException(); }
		}

		public override string PasswordStrengthRegularExpression
		{
			get { throw new NotImplementedException(); }
		}

		public override bool RequiresQuestionAndAnswer
		{
			get { throw new NotImplementedException(); }
		}

		/// <summary>
		/// Is uniqe email required?
		/// </summary>
		public override bool RequiresUniqueEmail
		{
			get { return false; }
		}

		public override string ResetPassword(string username, string answer)
		{
			throw new NotImplementedException();
		}

		public override bool UnlockUser(string userName)
		{
			throw new NotImplementedException();
		}

		public override void UpdateUser(System.Web.Security.MembershipUser user)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Check user's password to match.
		/// </summary>
		/// <param name="username">User's login.</param>
		/// <param name="password">User's password.</param>
		/// <returns>True if passwords mathes.</returns>
		public override bool ValidateUser(string username, string password)
		{
			if (string.IsNullOrWhiteSpace(username)
				|| string.IsNullOrWhiteSpace(password))
			{
				return false;
			}

			//string hash = EncryptPassword(password);
            MCPDB db = new MCPDB();
			User user = db.Users.SingleOrDefault(u => u.Username == username);

			if (user == null)
			{
				return false;
			}

			if (user.Password == password)
			{
				return true;
			}

			return false;
		}

		public AuthenticationResult Validate(string username, string password, IUnitOfWork unitOfWork)
		{
			if (string.IsNullOrWhiteSpace(username))
			{
				return new AuthenticationResult(AuthenticationResultType.NoUserEntered);
			}
			else if (string.IsNullOrWhiteSpace(password))
			{
				return new AuthenticationResult(AuthenticationResultType.NoPasswordEntered);
			}
			else
			{
				//string hash = EncryptPassword(password);
				
				User user = unitOfWork.AccountRepository.GetUser(username).Result;

				if (user == null)
				{
					return new AuthenticationResult(AuthenticationResultType.UnknownUser);
				}

				if (user.Password == password)
				{
					return new AuthenticationResult(AuthenticationResultType.Authorized);
				}
				else
				{
					return new AuthenticationResult(AuthenticationResultType.WrongPassword);
				}
			}
		}

		public string GetUserRole(string username)
		{
			string role = string.Empty;
			switch (username)
			{
				case "user":
				{
					role = "user";
					break;
				}
				case "admin":
				{
					role ="admin";
					break;
				}
			}

			return role;
		}
	}
}